package com.mao.crowd.controller;

import com.mao.crowd.api.MySQLRemoteService;
import com.mao.crowd.api.RedisRemoteService;
import com.mao.crowd.config.ShortMessageProperties;
import com.mao.crowd.constant.CrowdConstant;
import com.mao.crowd.entity.po.MemberPO;
import com.mao.crowd.entity.vo.MemberLoginVO;
import com.mao.crowd.entity.vo.MemberVO;
import com.mao.crowd.util.CrowdUtil;
import com.mao.crowd.util.ResultEntity;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author maomeng
 * @create 2021-06-21- 16:08
 */
@Controller
public class MemberController {

    @Autowired
    private ShortMessageProperties shortMessageProperties;

    @Autowired
    private RedisRemoteService redisremoteService;

    @Autowired
    private MySQLRemoteService mySQLRemoteService;

    /**
     * 退出登录的方法
     * @param session
     * @return
     */
    @RequestMapping("/auth/member/logout")
    public String doLogout(HttpSession session){
        session.invalidate();
        return "redirect:/";
    }

    /**
     * 执行登录的方法
     * @param loginacct 表单的账号
     * @param userpswd 表单的密码
     * @param modelMap
     * @param session
     * @return
     */
    @RequestMapping("/auth/member/do/login.html")
    public String doLogin(@RequestParam("loginacct") String loginacct,
                          @RequestParam("userpswd") String userpswd,
                          ModelMap modelMap,
                          HttpSession session){
        // 根据账号查询member对象
        ResultEntity<MemberPO> loginAcctRemote = mySQLRemoteService.getMemberPOByLoginAcctRemote(loginacct);
        if (ResultEntity.FAILED.equals(loginAcctRemote.getResult())){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,loginAcctRemote.getMessage());
            return "member-login";
        }
        MemberPO memberPO = loginAcctRemote.getData();

        if (memberPO == null){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_LOGIN_FAILED);
            return "member-login";
        }
        // 账号存在,开始比较密码

        String pswdDB = memberPO.getUserpswd();
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        // 比较加密后的密码,注意这里的顺序不能写反了,前面的是从表单获取的,不加密
        // 后面的是从数据库获取的,已经加密了
        boolean matches = passwordEncoder.matches(userpswd,pswdDB);
        if (!matches){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_LOGIN_FAILED);
            return "member-login";
        }
        MemberLoginVO memberLoginVO = new MemberLoginVO(memberPO.getId(), memberPO.getUsername(), memberPO.getEmail());
        session.setAttribute(CrowdConstant.ATTR_NAME_LOGIN_MEMBER,memberLoginVO);
        return "redirect:http://localhost:/auth/member/to/center/page.html";
    }

    /**
     * 执行用户注册
     * @param memberVO
     * @param modelMap
     * @return
     */
    @RequestMapping("/auth/do/member/register")
    public String register(MemberVO memberVO, ModelMap modelMap){
        // 获取用户输入的手机号
        String mobile = memberVO.getMobile();

        // 拼成redis中存储的key值
        String key = CrowdConstant.REDIS_CODE_PREFIX + mobile;

        // 从redis中读取key对应的value值
        ResultEntity<String> redisValueByKey = redisremoteService.getRedisValueByKey(key);

        // 如果从redis中取值不成功
        if (!ResultEntity.SUCCESS.equals(redisValueByKey.getResult())){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,redisValueByKey.getResult());

            return "member-reg";
        }

        String redisCode = redisValueByKey.getData();
        // 如果redis中没有指定手机号的验证码
        if (redisCode == null){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_CODE_NOT_EXISTS);
            return "member-reg";
        }
        // 如果用户输入的验证码和redis中的不一致
        if (!memberVO.getCode().equals(redisCode)){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_CODE_INVALID);
            return "member-reg";
        }

        // 如果表单提交的验证码和redis验证码一致,删除表单中保存的验证码信息
        redisremoteService.removeRedisValueByKey(key);
        // 执行密码加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String userpswd = memberVO.getUserpswd();
        String encodedPassword = passwordEncoder.encode(userpswd);
        memberVO.setUserpswd(encodedPassword);

        // 执行保存
        MemberPO memberPO = new MemberPO();
        BeanUtils.copyProperties(memberVO,memberPO);
        ResultEntity<String> saveResultEntity = mySQLRemoteService.saveMember(memberPO);
        // 如果账号已存在等原因注册不成功
        if (!ResultEntity.SUCCESS.equals(saveResultEntity.getResult())){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,saveResultEntity.getMessage());
            return "member-reg";
        }
        //保存后返回登录页面
        return "redirect:/auth/member/to/login/page.html";
    }

    /**
     * 发送验证码
     * @param mobile
     * @return
     */
    @ResponseBody
    @RequestMapping("/auth/member/send/short/message.json")
    public ResultEntity<String> sendMessage(@RequestParam("mobile") String mobile) {

        // 发送验证码到mobile手机号(参数放入yml配置文件)
        ResultEntity<String> sendMessageResultEntity = CrowdUtil.sendShortMessage(
                shortMessageProperties.getHost(),
                shortMessageProperties.getPath(),
                shortMessageProperties.getMethod(),
                shortMessageProperties.getAppcode(),
                mobile,
                shortMessageProperties.getSmsSignId(),
                shortMessageProperties.getTemplateId());
        // 如果短信发送成功
        if (ResultEntity.SUCCESS.equals(sendMessageResultEntity.getResult())){
            // 如果发送成功，将验证码存入redis
            String code = sendMessageResultEntity.getData();
            System.out.println(code);
            String key = CrowdConstant.REDIS_CODE_PREFIX + mobile;
            System.out.println(key);
            // 五分钟验证码超时
            ResultEntity<String> saveCodeResultEntity = redisremoteService.setRedisKeyValueRemoteWithTimeOut(key, code, 5, TimeUnit.MINUTES);
            // 如果验证码保存成功
            if (ResultEntity.SUCCESS.equals(saveCodeResultEntity.getResult())){
                System.out.println(saveCodeResultEntity);
                return ResultEntity.successWithOutData();
            }else {
                // 如果验证码保存失败
                return saveCodeResultEntity;
            }
        }else {
            // 如果短信发送失败
            return sendMessageResultEntity;
        }
    }
}
